<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>Platform Independent Non-Volatile Storage Abstractions</title>
<meta name="authors" content="David Moss  Junzhao Du  Prabal Dutta  Deepak Ganesan  Kevin Klues  Manju  Ajay Martin  and Gaurav Mathur" />
<style type="text/css">

/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2009-02-03 23:07:32 $
:version: $Revision: 1.2 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/
body {
  font-family: Times;
  font-size: 16px;
}

.first {
  margin-top: 0 ! important }

.last {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1 {
  font-family: Arial, sans-serif;
  font-size: 20px;
}

h1.title {
 text-align: center;
 font-size: 32px;
}

h2 {
 font-size: 16px;
 font-family: Arial, sans-serif;
}

h2.subtitle {
  text-align: center }

h3 {
 font-size: 12px;
 font-family: Arial, sans-serif;
}

hr {
  width: 75% }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;
  background-color: #eeeeee;
  border-color: #000000;
  border-width: thin; 
  font-size: 14px
}

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em;
}

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap;
  }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

tt {}

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="platform-independent-non-volatile-storage-abstractions">
<h1 class="title">Platform Independent Non-Volatile Storage Abstractions</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">TEP:</th><td class="field-body">128</td>
</tr>
<tr class="field"><th class="docinfo-name">Group:</th><td class="field-body">Storage Working Group</td>
</tr>
<tr class="field"><th class="docinfo-name">Type:</th><td class="field-body">Documentary</td>
</tr>
<tr><th class="docinfo-name">Status:</th>
<td>DRAFT</td></tr>
<tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">2.x</td>
</tr>
<tr><th class="docinfo-name">Authors:</th>
<td>David Moss
<br />Junzhao Du
<br />Prabal Dutta
<br />Deepak Ganesan
<br />Kevin Klues
<br />Manju
<br />Ajay Martin
<br />and Gaurav Mathur</td></tr>
</tbody>
</table>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">This memo documents a part of TinyOS for the TinyOS Community, and
requests discussion and suggestions for improvements.  Distribution
of this memo is unlimited. This memo is in full compliance with
TEP 1.</p>
</div>
<div class="section">
<h1><a id="abstract" name="abstract">Abstract</a></h1>
<p>The storage abstractions proposed by TEP 103 are implemented on a
platform-dependent basis.  A version of BlockStorage, ConfigStorage,
and LogStorage were created from the ground up for both the
AT45DB and ST M25P80 flash chips.  Looking forward into the further
growth and development of hardware, rebuilding each of these storage
layers for every new flash chip will be time consuming and cause
compatibility issues.</p>
<p>We propose a layer of abstraction to reside between a chip-dependent
flash chip implementation and platform-independent storage
implementations.  This abstraction layer should provide methods
to perform basic flash operations (read, write, erase, flush, crc),
as well as provide information about the physical properties of the
flash chip.  Efficiency concerns are mitigated by the fact that each
platform-independent abstraction is implemented in a platform-dependent
manner, allowing it to exist on different types of memory such as
NAND flash, NOR flash, and EEPROM.  This abstraction layer should
allow one implementation of each storage solution to operate across
many different platforms.</p>
</div>
<div class="section">
<h1><a id="introduction" name="introduction">1. Introduction</a></h1>
<p>The implementations of the BlockStorage, ConfigStorage, and LogStorage
layers described in TEP 103 [1] are platform dependent.  Platform-
dependent implementations can cause behavioral and usage differences
as well as compiling problems when attempting to port an application
written on one platform to another.  A true abstraction layer would
exhibit the same set of interfaces and no differences in behavior when
implemented across various types of non-volatile memory.</p>
<p>A well defined non-volatile memory abstraction layer should allow core
functionality to work on a variety of platforms without modification.
Some flash chips may provide extra functionality.  If a particular
applications on a specific platform wants to take advantage of
extra functionality provided by a flash chip, it still has the opportunity
to access those features directly with the understanding that its
implementation is no longer considered platform-independent.</p>
<div class="section">
<h2><a id="platform-dependent-volume-settings" name="platform-dependent-volume-settings">1.1 Platform-dependent volume settings</a></h2>
<p>Differences exist between the TEP 103 storage implementations
on the AT45DB, ST M25P80, and PXA27X P30 flash chips.</p>
<p>First, volume information is defined using two distinct methods. As
was discussed in TEP 103, an XML file is responsible for the
allocation of flash memory into volumes at compile time.  Individual
storage layers can then mount to the defined volumes, which
allows those layers to share the flash memory resource amongst
each other.</p>
<p>The AT45DB implementation running on mica* platforms converts the
information presented in the application's volumes XML file into
information accessible through macros::</p>
<pre class="literal-block">
#ifndef STORAGE_VOLUMES_H
#define STORAGE_VOLUMES_H

enum {
  VOLUME_BLOCKTEST,
};

#endif
#if defined(VS)
VS(VOLUME_BLOCKTEST, 1024)
#undef VS
#endif
#if defined(VB)
VB(VOLUME_BLOCKTEST, 0)
#undef VB
#endif
</pre>
<p>The ST M25P80 implementation running on TelosB/Tmote platforms,
on the other hand, converts the information in the volumes XML
file into an array of constants::</p>
<pre class="literal-block">
#ifndef __STORAGE_VOLUME_H__
#define __STORAGE_VOLUME_H__

#include &quot;Stm25p.h&quot;

#define VOLUME_BLOCKTEST 0

static const stm25p_volume_info_t STM25P_VMAP[ 1 ] = {
    { base : 0, size : 4 },
};

#endif
</pre>
<p>Furthermore, the two implementations defined incompatible interfaces for
accessing information about volumes.  For example, the AT45DB interface
provides the following::</p>
<pre class="literal-block">
interface At45dbVolume {
  command at45page_t remap(at45page_t volumePage);
  command at45page_t volumeSize();
}
</pre>
<p>The ST M25P80 interface defines a different interface, which allows
applications to access the volume settings directly through the
stm25p_volume_info_t array::</p>
<pre class="literal-block">
interface Stm25pVolume {
  async event volume_id_t getVolumeId();
}
</pre>
<p>Accessing volume information is very platform-dependent.
A single method should be integrated to access volume
settings and non-volatile memory properties across any platform.</p>
<p>Another issue exists with the previous concept of volumes.  Any storage
solution that wishes to retain valid data while erasing invalid data
MUST have access to at least two erase units.  Circular logging,
configuration storage, variable storage, dictionary storage, file
systems, and more all require a minimum of two erase units to be
implemented effectively.  One erase unit can be used to erase
all the invalid data while other erase unit(s) retains any valid data.</p>
<p>Therefore, the minimum allowable volume size should be twice the size
of a single erase unit to effectively support the majority of
storage applications.  The XML tools that process and allocate
volumes should prevent a user from defining a volume too small::</p>
<pre class="literal-block">
+------------+--------+------------+-----------+------------+
|            | AT45DB |   ST M25P  |   PXA27x  | K9K1G08R0B |
+------------+--------+------------+-----------+------------+
| Min.Volume |  512B  | 512B-128kB | 128-256kB | 16kB-64kB  |
+------------+--------+------------+-----------+------------+
</pre>
</div>
<div class="section">
<h2><a id="platform-dependent-component-signatures" name="platform-dependent-component-signatures">1.2 Platform-dependent component signatures</a></h2>
<p>The storage components' signatures differ across implementations.
For example, the PXA27X P30 flash defines &quot;P30BlockC&quot;, &quot;P30ConfigC&quot;,
and &quot;P30LogC&quot; in place of &quot;BlockStorageC&quot;, &quot;ConfigStorageC&quot;, and
&quot;LogStorageC&quot;.  Furthermore, the BlockStorageC configuration in the
AT45DB implementation takes the following form::</p>
<pre class="literal-block">
generic configuration BlockStorageC(volume_id_t volid) {
  provides {
    interface BlockWrite;
    interface BlockRead;
  }
}
</pre>
<p>while the ST M25P80 implementation adds another interface::</p>
<pre class="literal-block">
generic configuration BlockStorageC( volume_id_t volume_id ) {
  provides interface BlockRead;
  provides interface BlockWrite;
  provides interface StorageMap;
}
</pre>
<p>The StorageMap interface on the M25P80 flash chip simply allows
an application to convert a volume-based virtual address into
a physical address on flash.  Although it is a good idea, it
is not consistent with other platforms' defined interfaces.</p>
</div>
</div>
<div class="section">
<h1><a id="directstorage" name="directstorage">2. DirectStorage</a></h1>
<div class="section">
<h2><a id="differences-and-advantages" name="differences-and-advantages">3.1 Differences and advantages</a></h2>
<p>The core current BlockStorage, ConfigStorage, and LogStorage
layers can all be implemented on a platform-independent abstraction
layer.  Providing an interface that allows direct, unimpeded
access to the memory below while offering information about
the properties of that memory is the first step in doing so.</p>
<p>The DirectStorage interface was created to as part of the answer to this
issue.  DirectStorage resembles the BlockStorage interface in many ways,
with two significant exceptions:</p>
<p>1. Erase operation
BlockStorage's behavior erases the entire volume at a time, which may
consist of multiple erase units.  DirectStorage allows erases to occur
on per-erase unit basis.  Therefore, if only a portion of the volume
needs to be erased, it can.</p>
<p>2. Organization
BlockStorage defines two different interfaces for interacting with the
flash:  BlockRead and BlockWrite.  These two interfaces are combined
into one interface.  The getSize() command provided by the BlockRead
interface is removed and replaced with VolumeSettings, which will be
discussed later.  Also, sync()/syncDone() is replaced with
flush/flushDone(), which is responsible for writing any data that
has not already been written to non-volatile memory.  Although
the crc() command can technically exist above BlockStorage as
well as DirectStorage, it remains in DirectStorage for its ease
of use.</p>
<p>Finally, layers should have the ability to be added beneath DirectStorage
to further optimize and enable memory operation.  For example, the
ST M25P80 flash does not have any on-board RAM buffers, so it
is up to the microcontroller to buffer and flush out data to write units.
This functionality may not be desirable on all applications because
it uses valuable microcontroller resources; therefore, it should
be removable as layers can be added and removed from radio stack
architecture.</p>
<p>Other memory types may require extra support in and underneath
the hood of DirectStorage as well. NAND flash, for example,
requires bad block management and error correction. This functionality
can be implemented without changing the behavior of the DirectStorage
interface above.</p>
</div>
<div class="section">
<h2><a id="directstorage-interface" name="directstorage-interface">3.2 DirectStorage Interface</a></h2>
<p>The DirectStorage interface is described below.  Each &quot;addr&quot; variable
is a virtual address, with 0x0 relative to the base address of the
volume.  This base address may actually be physically located
somewhere else on the non-volatile memory::</p>
<pre class="literal-block">
interface DirectStorage {

  command error_t read(uint32_t addr, void *buf, uint32_t len);

  command error_t write(uint32_t addr, void *buf, uint32_t len);

  command error_t erase(uint16_t eraseUnitIndex);

  command error_t flush();

  command error_t crc(uint32_t addr, uint32_t len, uint16_t baseCrc);



  event void readDone(uint32_t addr, void *buf, uint32_t len, error_t error);

  event void writeDone(uint32_t addr, void *buf, uint32_t len, error_t error);

  event void eraseDone(uint16_t eraseUnitIndex, error_t error);

  event void flushDone(error_t error);

  event void crcDone(uint16_t calculatedCrc, uint32_t addr, uint32_t len, error_t error);

}
</pre>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">read(uint32_t</span> <span class="pre">addr,</span> <span class="pre">void</span> <span class="pre">'*buf',</span> <span class="pre">uint32_t</span> <span class="pre">len);</span></tt></dt>
<dd><ul class="first last simple">
<li>Read 'len' bytes into <tt class="docutils literal"><span class="pre">*buf</span></tt> from the given address</li>
<li>Returns FAIL if the volume is already in use</li>
<li>Signals readDone(...) when complete.</li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">write(uint32_t</span> <span class="pre">addr,</span> <span class="pre">void</span> <span class="pre">'*buf',</span> <span class="pre">uint32_t</span> <span class="pre">len);</span></tt></dt>
<dd><ul class="first last simple">
<li>Write 'len' bytes from <tt class="docutils literal"><span class="pre">*buf</span></tt> starting at the given address</li>
<li>Returns FAIL if the volume is already in use</li>
<li>Signals writeDone(...) when complete.</li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">erase(uint16_t</span> <span class="pre">eraseUnitIndex);</span></tt></dt>
<dd><ul class="first last simple">
<li>Erase a single 0-indexed erase unit</li>
<li>Returns FAIL if the volume is already in use</li>
<li>Signals eraseDone(...) when complete.</li>
</ul>
</dd>
<dt>flush()</dt>
<dd><ul class="first last simple">
<li>All data that has been previously written and is not yet located on
non-volatile memory should be immediately stored to non-volatile memory.</li>
<li>Returns FAIL if the operation cannot be completed at this time</li>
<li>Signals flushDone(...) when complete.</li>
</ul>
</dd>
<dt>crc(uint32_t addr, uint32_t len, uint16_t baseCrc);</dt>
<dd><ul class="first last simple">
<li>Calculate the CRC of 'len' bytes starting at the given address, using
the given baseCrc as a seed.</li>
<li>Returns FAIL if the volume is already in use</li>
<li>Signals crcDone(...) when complete.</li>
</ul>
</dd>
</dl>
</div>
<div class="section">
<h2><a id="directmodify-interface" name="directmodify-interface">3.3 DirectModify Interface</a></h2>
<p>Some memory types have the ability to modify their contents without
destroying surrounding data.</p>
<p>The AT45DB NOR-flash, for example, is able to do this because
it has built in RAM buffers coupled with small erase unit sizes.
The physical RAM buffers perform a read-modify-write operation to
effectively change the contents of flash, allowing it to emulate
the behavior of an EEPROM with the speed and efficiency of NOR-flash.</p>
<p>The ATmega128 microcontroller has 4kB of internal EEPROM memory which
can be directly modified.  Also, the MSP430 has 256 bytes of internal
NOR-flash memory which is divided into two segments of 128 bytes each.
When implemented properly, this NOR-flash memory can be modified in a
fault-tolerant manner.</p>
<p>The ST M25P80 NOR-flash cannot support modification without sacrificing
significant overhead.  It has 16 erase units that are 64kB each,
which is too large to effectively modify bytes.</p>
<p>While not all memories support modification, a unified interface
should exist to interact with memories that do.  This interface
should be access with the understanding that applications built
on top may not be portable to all memory types. Also, DirectStorage
and DirectModify are mounted to their own individual volumes, so
DirectModify cannot share its allocated memory resources with
a DirectStorage interface::</p>
<pre class="literal-block">
interface DirectModify {

  command error_t modify(uint32_t addr, void *buf, uint32_t len);

  command error_t read(uint32_t addr, void *buf, uint32_t len);

  command error_t erase(uint16_t eraseUnitIndex);

  command error_t flush();

  command error_t crc(uint32_t addr, uint32_t len, uint16_t baseCrc);

  command bool isSupported();


  event void modified(uint32_t addr, void *buf, uint32_t len, error_t error);

  event void readDone(uint32_t addr, void *buf, uint32_t len, error_t error);

  event void eraseDone(uint16_t eraseUnitIndex, error_t error);

  event void flushDone(error_t error);

  event void crcDone(uint16_t calculatedCrc, uint32_t addr, uint32_t len, error_t error);

}
</pre>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">modify(uint32_t</span> <span class="pre">addr,</span> <span class="pre">void</span> <span class="pre">*buf,</span> <span class="pre">uint32_t</span> <span class="pre">len)</span></tt></dt>
<dd><ul class="first last simple">
<li>Modify 'len' bytes located on non-volatile memory at the given address,
replacing them with data from the given buffer</li>
<li>Returns FAIL if the volume is already in use</li>
<li>Signals modified(...) when the operation is complete</li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">read(uint32_t</span> <span class="pre">addr,</span> <span class="pre">void</span> <span class="pre">*buf,</span> <span class="pre">uint32_t</span> <span class="pre">len)</span></tt></dt>
<dd><ul class="first last simple">
<li>Read 'len' bytes into <tt class="docutils literal"><span class="pre">*buf</span></tt> from the given address</li>
<li>Same as DirectStorage.read(...)</li>
<li>Returns FAIL if the volume is already in use</li>
<li>Signals readDone(...) when complete.</li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">erase(uint16_t</span> <span class="pre">eraseUnitIndex);</span></tt></dt>
<dd><ul class="first last simple">
<li>Erase a single 0-indexed erase unit</li>
<li>Returns FAIL if the volume is already in use</li>
<li>Signals eraseDone(...) when complete.</li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">flush()</span></tt></dt>
<dd><ul class="first last simple">
<li>All data that has been previously written and is not yet located on
non-volatile memory should be immediately stored to non-volatile memory.</li>
<li>Same behavior as flush() methods found in Java</li>
<li>Returns FAIL if the operation cannot be completed at this time</li>
<li>Signals flushDone(...) when complete.</li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">crc(uint32_t</span> <span class="pre">addr,</span> <span class="pre">uint32_t</span> <span class="pre">len,</span> <span class="pre">uint16_t</span> <span class="pre">baseCrc);</span></tt></dt>
<dd><ul class="first last simple">
<li>Calculate the CRC of 'len' bytes starting at the given address, using
the given baseCrc as a seed.</li>
<li>Returns FAIL if the volume is already in use</li>
<li>Signals crcDone(...) when complete.</li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">isSupported()</span></tt></dt>
<dd><ul class="first last simple">
<li>Returns TRUE if DirectModify is available on the current memory type</li>
</ul>
</dd>
</dl>
</div>
<div class="section">
<h2><a id="volumesettings-interface" name="volumesettings-interface">3.4 VolumeSettings Interface</a></h2>
<p>As was shown in Section 1.1, finding information about the current
volume required platform-dependent methods of access.  VolumeSettings
provides a unified method of accessing information about the underlying
memory chip and volume settings.</p>
<p>VolumeSettings MUST be implemented separately for DirectStorage and
DirectModify, not only because those abstractions will exist on
separate volumes, but also because the DirectModify interface may
change the available size of the volume to support certain memory
types such as NAND- and NOR-flash::</p>
<pre class="literal-block">
interface VolumeSettings {

  command uint32_t getVolumeSize();

  command uint32_t getTotalEraseUnits();

  command uint32_t getEraseUnitSize();

  command uint32_t getTotalWriteUnits();

  command uint32_t getWriteUnitSize();

  command uint8_t getFillByte();

  command uint8_t getEraseUnitSizeLog2();

  command uint8_t getWriteUnitSizeLog2();

}
</pre>
<dl class="docutils">
<dt>getVolumeSize()</dt>
<dd><ul class="first last simple">
<li>Returns the size of the volume the DirectStorage layer
is mounted to, in bytes</li>
</ul>
</dd>
<dt>getTotalEraseUnits()</dt>
<dd><ul class="first last simple">
<li>Returns the total number of erase units on the mounted volume</li>
</ul>
</dd>
<dt>getEraseUnitSize()</dt>
<dd><ul class="first last simple">
<li>Returns the size of an individual erase unit, in bytes</li>
</ul>
</dd>
<dt>getTotalWriteUnits()</dt>
<dd><ul class="first last simple">
<li>Returns the total number of write units on the mounted volume</li>
</ul>
</dd>
<dt>getWriteUnitSize()</dt>
<dd><ul class="first last simple">
<li>Returns the size of an individual write unit, in bytes</li>
</ul>
</dd>
<dt>getFillByte()</dt>
<dd><ul class="first last simple">
<li>Returns the default byte value found on the memory after an erase,
which is typically 0xFF</li>
</ul>
</dd>
<dt>getEraseUnitSizeLog2()</dt>
<dd><ul class="first last simple">
<li>Returns the size of an erase unit in Log2 format for ease of
calculations</li>
</ul>
</dd>
<dt>getWriteUnitSizeLog2()</dt>
<dd><ul class="first last simple">
<li>Returns the size of a write unit in Log2 format for ease of
calculations</li>
</ul>
</dd>
</dl>
</div>
</div>
<div class="section">
<h1><a id="author-s-address" name="author-s-address">4. Author's Address</a></h1>
<div class="line-block">
<div class="line">David Moss</div>
<div class="line">Rincon Research Corporation</div>
<div class="line">101 N. Wilmot, Suite 101</div>
<div class="line">Tucson, AZ  85750</div>
<div class="line"><br /></div>
<div class="line">phone - +1 520 519 3138</div>
<div class="line">phone - +1 520 519 3146</div>
<div class="line">email ? <a class="reference" href="mailto:dmm&#64;rincon.com">dmm&#64;rincon.com</a></div>
<div class="line"><br /></div>
<div class="line">Junzhao Du</div>
<div class="line">Contact -</div>
<div class="line"><br /></div>
<div class="line">Prabal Dutta</div>
<div class="line">Contact -</div>
<div class="line"><br /></div>
<div class="line">Deepak Ganesan</div>
<div class="line">Contact -</div>
<div class="line"><br /></div>
<div class="line">Kevin Klues</div>
<div class="line">Contact -</div>
<div class="line"><br /></div>
<div class="line">Manju</div>
<div class="line">Contact -</div>
<div class="line"><br /></div>
<div class="line">Ajay Martin</div>
<div class="line">Contact -</div>
<div class="line"><br /></div>
<div class="line">Gaurav Mathur</div>
<div class="line">Contact -</div>
</div>
</div>
<div class="section">
<h1><a id="citations" name="citations">5. Citations</a></h1>
<table class="docutils footnote" frame="void" id="id1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id1">[1]</a></td><td>TEP 103: Permanent Data Storage (Flash). <a class="reference" href="http://tinyos.cvs.sourceforge.net/">http://tinyos.cvs.sourceforge.net/</a><em>checkout</em>/tinyos/tinyos-2.x/doc/html/tep103.html</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id2" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id2">[2]</a></td><td>Atmel AT45DB041B datasheet. <a class="reference" href="http://www.atmel.com/dyn/resources/prod_documents/DOC1432.PDF">http://www.atmel.com/dyn/resources/prod_documents/DOC1432.PDF</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id3" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id3">[3]</a></td><td>ST M25P80 datasheet. <a class="reference" href="http://www.st.com/stonline/products/literature/ds/8495/m25p80.pdf">http://www.st.com/stonline/products/literature/ds/8495/m25p80.pdf</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id4" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id4">[4]</a></td><td>K9K1G08R0B datasheet. <a class="reference" href="http://www.samsung.com/Products/Semiconductor/NANDFlash/SLC_SmallBlock/1Gbit/K9K1G08R0B/ds_k9k1g08x0b_rev10.pdf">http://www.samsung.com/Products/Semiconductor/NANDFlash/SLC_SmallBlock/1Gbit/K9K1G08R0B/ds_k9k1g08x0b_rev10.pdf</a></td></tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
